﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Phoenix.Xna.Framework.Components.Cameras;
using Phoenix.Xna.Framework.Graphics;

namespace Phoenix.Xna.Framework.Components.Terrain
{
    public class TerrainShader : Shader<TerrainDataBuffer>
    {
        /// <summary>
        /// Gets or sets the world matrix used for rendering the terrain.
        /// </summary>
        public Matrix World
        {
            get { return EffectMap.GetParameter<Matrix>("World"); }
            set { EffectMap.SetParameter<Matrix>("World", value); }
        }

        /// <summary>
        /// Gets or sets the camera view matrix used for rendering the terrain.
        /// </summary>
        public Matrix View
        {
            get { return EffectMap.GetParameter<Matrix>("View"); }
            set { EffectMap.SetParameter<Matrix>("View", value); }
        }

        /// <summary>
        /// Gets or sets the camera projection matrix used for rendering the terrain.
        /// </summary>
        public Matrix Projection
        {
            get { return EffectMap.GetParameter<Matrix>("Projection"); }
            set { EffectMap.SetParameter<Matrix>("Projection", value); }
        }
        public Vector3 SunlightDirection
        {
            get { return EffectMap.GetParameter<Vector3>("SunlightDirection"); }
            set { EffectMap.SetParameter<Vector3>("SunlightDirection", value); }
        }
        public Vector3 SunlightColor
        {
            get { return EffectMap.GetParameter<Vector3>("SunlightColor"); }
            set { EffectMap.SetParameter<Vector3>("SunlightColor", value); }
        }
        public Vector3 AmbientColor
        {
            get { return EffectMap.GetParameter<Vector3>("AmbientColor"); }
            set { EffectMap.SetParameter<Vector3>("AmbientColor", value); }
        }
        public bool IsHighQuality
        {
            get { return EffectMap.GetParameter<bool>("HighQualityDetailMapping"); }
            set { EffectMap.SetParameter<bool>("HighQualityDetailMapping", value); }
        }
        public float DetailScale
        {
            get { return EffectMap.GetParameter<float>("DetailScale"); }
            set { EffectMap.SetParameter<float>("DetailScale", value); }
        }
        public float DiffuseScale
        {
            get { return EffectMap.GetParameter<float>("DiffuseScale"); }
            set { EffectMap.SetParameter<float>("DiffuseScale", value); }
        }
        public float BlendMapScaler
        {
            get { return EffectMap.GetParameter<float>("BlendMapScaler"); }
            set { EffectMap.SetParameter<float>("BlendMapScaler", value); }
        }
        public Texture2D DetailTexture
        {
            get { return EffectMap.GetParameter<Texture2D>("DetailTexture"); }
            set { EffectMap.SetParameter<Texture2D>("DetailTexture", value); }
        }
        public float DetailMapStrength
        {
            get { return EffectMap.GetParameter<float>("DetailMapStrength"); }
            set { EffectMap.SetParameter<float>("DetailMapStrength", value); }
        }
        public float Gama
        {
            get { return EffectMap.GetParameter<float>("Gama"); }
            set { EffectMap.SetParameter<float>("Gama", value); }
        }
        public BlendMap BlendMap1 { get; private set; }
        public BlendMap BlendMap2 { get; private set; }
        public BlendMap BlendMap3 { get; private set; }
        public Vector3 Translation { get; set; }

        public TerrainShader(string asset, bool isEffectMap)
            : base(asset, isEffectMap)
        {
        }

        public TerrainShader(EffectMap effectMap)
            : base(effectMap)
        {
        }

        public TerrainShader(string id, string asset, bool isEffectMap)
            : base(id, asset, isEffectMap)
        {
        }

        public TerrainShader(string id, EffectMap effectMap)
            : base(id, effectMap)
        {
        }

        #region Shader Members

        public override EffectMap EffectMap
        {
            get { return base.EffectMap; }
            set
            {
                base.EffectMap = value;
                BlendMap1 = new BlendMap(EffectMap, "BlendMap1", "Texture1", "Texture2", "Texture3", "Texture4");
                BlendMap1 = new BlendMap(EffectMap, "BlendMap2", "Texture5", "Texture6", "Texture7", "Texture8");
                BlendMap1 = new BlendMap(EffectMap, "BlendMap3", "Texture9", "Texture10", "Texture11", "Texture12");
            }
        }

        public override void Draw(GameTime gameTime, TerrainDataBuffer state)
        {
            if (!state.VertexBuffer.IsDisposed)
            {
                World = Matrix.Identity * Matrix.CreateTranslation(Translation);
                View = Camera.ActiveCamera.View;
                Projection = Camera.ActiveCamera.Projection;
                Engine.Instance.GraphicsDevice.Vertices[0].SetSource(state.VertexBuffer, 0, VertexPositionNormal.SizeInBytes);
                Engine.Instance.GraphicsDevice.Indices = state.IndexBuffer;

                foreach (EffectPass pass in EffectMap.Begin())
                {
                    pass.Begin();
                    Engine.Instance.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, state.NumberOfVertices, 0, state.NumberOfIndices);
                    pass.End();
                }

                EffectMap.End();
            }
        }

        #endregion
    }
}
